(function () {
	'use strict';
	var DeviceOrientationControl = function (params) {
		var defaults = {
			onChange() {
			},
			onOrient() {
			}
		}

		params = params || {};
		for (var def in defaults) {
			if (typeof params[def] === 'undefined') {
				params[def] = defaults[def];
			}
			else if (typeof params[def] === 'object') {
				for (var deepDef in defaults[def]) {
					if (typeof params[def][deepDef] === 'undefined') {
						params[def][deepDef] = defaults[def][deepDef];
					}
				}
			}
		}
		this.config = params;
		this.lon = this.lat = this.deltaLon = this.deltaLat = 0;
		this.moothFactor = 10;
		this.boundary = 320;
		this.direction = window.orientation || 0;
		this.bind();
		this.isFixed = false;
	}
	DeviceOrientationControl.prototype.bind = function () {
		if (typeof DeviceMotionEvent.requestPermission === 'function') {
			// IOS12.2以上
			DeviceMotionEvent.requestPermission()
				.then(permissionState => {
					if (permissionState === 'granted') {
						window.addEventListener('deviceorientation', this._bindChange = this._onChange.bind(this));
						window.addEventListener('orientationchange', this._bindOrient = this._onOrient.bind(this));
					}
				})
				.catch(console.error);
		} else {
			// 其他系统
			window.addEventListener('deviceorientation', this._bindChange = this._onChange.bind(this));
			window.addEventListener('orientationchange', this._bindOrient = this._onOrient.bind(this));
		}


	};
	DeviceOrientationControl.prototype.destroy = function () {
		window.removeEventListener('deviceorientation', this._bindChange, { passive: false });
		window.removeEventListener('orientationchange', this._bindOrient, { passive: false });
	};
	DeviceOrientationControl.prototype._onOrient = function (event) {

		this.direction = window.orientation;

		this._config.onOrient(this.direction);
		this.lastLon = this.lastLat = undefined;
	};
	DeviceOrientationControl.prototype._mooth = function (x, lx) { //插值为了平滑些
		if (lx === undefined) {
			return x;
		}
		//0至360,边界值特例，有卡顿待优化
		if (Math.abs(x - lx) > this.boundary) {
			if (lx > this.boundary) {
				var offsetx = 360 + x - lx;
				x = lx + offsetx / this.moothFactor;
				if (x > 360) x -= 360;
			} else {
				var offsetx = 360 - x + lx;
				x = lx - offsetx / this.moothFactor;
				if (x < 0) x += 360;
			}
		}
		//滤波降噪
		else x = lx + (x - lx) / this.moothFactor;
		return x;
	};
	DeviceOrientationControl.prototype._onChange = function (evt) {
		switch (this.direction) {
			case 0:
				this.lon = -(evt.alpha + evt.gamma);
				this.lat = evt.beta - 90;
				break;
			case 90:
				this.lon = Math.abs(evt.beta) - evt.alpha;
				this.lat = evt.gamma < 0 ? -90 - evt.gamma : 90 - evt.gamma;
				break;
			case -90:
				this.lon = -(evt.alpha + Math.abs(evt.beta));
				this.lat = evt.gamma > 0 ? evt.gamma - 90 : 90 + evt.gamma;
				break;
		}

		this.lon = this.lon > 0 ? this.lon % 360 : this.lon % 360 + 360;
		if (!this.isFixed) {
			this.lastLat = this.lat;
			this.lastLon = this.lon;
			this.isFixed = true;
		}
		//插值为了平滑，修复部分android手机陀螺仪数字有抖动异常的
		this.lat = this._mooth(this.lat, this.lastLat);
		this.lon = this._mooth(this.lon, this.lastLon);


		this.deltaLat = this.lat - this.lastLat;
		this.deltaLon = this.lon - this.lastLon;
		if (this.deltaLon < -300) this.deltaLon += 360;
		if (this.deltaLon > 300) this.deltaLon -= 360;

		this.lastLat = this.lat;
		this.lastLon = this.lon;
		this.config.onChange({
			lon: this.lon,
			lat: this.lat,
			deltaLon: this.deltaLon,
			deltaLat: this.deltaLat
		});
	};
	window.DeviceOrientationControl = DeviceOrientationControl;
})(window);
